{***************************************************************
    SpyGestion  Copyright (C) 2008 Christophe KOALI <nature2gas@gmail.com>
    
    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.
    
    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.
    
    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
    
****************************************************************}
unit modTunnelUsers;

interface

uses Classes,
     SysUtils,
     modMd5,
     sFonctionsChaines;


const
    CNT_TUNNEL_USER_FLAG_ISBANNED    = 1;
    CNT_TUNNEL_USER_FLAG_ISROOT      = 2;
    CNT_TUNNEL_USER_FLAG_DO_NOT_SAVE = 4;

    CNT_TUNNEL_USER_FLAG_FORCE_SAVE  = 8;


type
    TTunnelUserGameDroit = (tudFlotteEnvoiDePartout,
                        tudFlotteEnvoiSurDebris,
                        tudFlotteEnvoiSurSesProprePlanete,
                        tudFlotteEnvoiCanMettreRessource,
                        tudFlotteAllowOrderAttack,
                        


                        tudCancelBat,
                        tudCancelRecherche,
                        
                        tudMessageEnvoi,
                        tudMessageSuppr,
                        tudMessageVoir,

                        tudDefenseCanUse,
                        tudChantierCanUse,

                        tudAlliancePage,
                        tudRecherchePage,
                        tudListDami,

                        tudGalaxie,
                        tudRessourceCanChangePourcent,

                        tudLogout,
                        tudAllowRelogin);



   TTunnelUserRobotDroit = (tudServiceLoadProfil,
                            tudServiceModifProfil);


const
   CNT_VAR_ROBOT_USEREDIT_COND_DROITS : array[TTunnelUserGameDroit] of string =
                      ('COND_FlotteEnvoiDePartout',
                       'COND_FlotteEnvoiSurDebris',
                       'COND_FlotteEnvoiSurSesProprePlanete',
                       'COND_FlotteEnvoiCanMettreRessource',
                       'COND_FlotteAllowOrderAttack',

                       'COND_CancelBat',
                       'COND_CancelRecherche',

                       'COND_MessageEnvoi',
                       'COND_MessageSuppr',
                       'COND_MessageVoir',

                       'COND_DefenseCanUse',
                       'COND_ChantierCanUse',

                       'COND_AlliancePage',
                       'COND_RecherchePage',
                       'COND_ListDami',

                       'COND_Galaxie',
                       'COND_RessourceCanChangePourcent',

                       'COND_Logout',
                       'COND_AllowRelogin');

type


    TSTunnelUserGameDroit = set of TTunnelUserGameDroit;

    TTunnelUserInfos = record
        // nom utilisé pour le login
        // clé primaire et unique
        Username: string[32];

        // hash md5
        Password: TMd5HashInfo;

        // Flags divers (comme par exemple banni)
        Flags   : longword;

        LastConn    : int64;
        DateCreation: int64;

        Droits: TSTunnelUserGameDroit;
    end;




    PTunnelUserInfos = ^TTunnelUserInfos;
    TCollectionTunnelUserInfos = class(TList)
    private
       {--------------------------------------------------}
       {Elements spécialisés de la classes}
       FFichier: string;

      
       {--------------------------------------------------}
       {Gestion des pointeurs}
       // Utilisé pour la propriété Itemx
       function GetItemx(Index: integer): TTunnelUserInfos;
    public
       property FichierSave: string read FFichier write FFichier;
       
       {--------------------------------------------------}
       {Gestion des pointeurs}
       // *** Ajout de pointeurs
       // Renvoi le pointeur de l'élément ajouté
       function Add(Element: TTunnelUserInfos): PTunnelUserInfos;
      
       // Simple ajout de pointeur
       procedure SimpleAdd(Pointeur: PTunnelUserInfos);
      
       // Renvoi le pointeur de l'élément ajouté/modifié
       // Utilise Get_Index pour vérifier si l'élément doit être mis à jour
       function Add_Update(Element: TTunnelUserInfos): PTunnelUserInfos;
      
      
       // *** Suppression de pointeur
       // Libère et supprime le pointeur Index
       // Renvoi True si réussit, False si hors limite ou erreur
       function Delete(Index: integer): boolean; overload;

       // Cherche Element avec Get_Index et supprime LE
       // PREMIER pointeur trouvé, renvoi True si réussit
       function Delete(Element: string): boolean; overload;

      
       // *** Effacement de la liste de pointeur
       procedure Clear; override;
      
      
       // *** Requete sur la liste de pointeur
       function Get_Index(const Element: string): integer;
       function Get_Pointeur(const Element: string): PTunnelUserInfos;
       function Get_Item(Index: integer): TTunnelUserInfos;
       property Itemx[Index: integer]: TTunnelUserInfos read GetItemx;
      

      
       {--------------------------------------------------}
       {Procédures et fonctions spécialisées de la classes}
       // Destructeur
       destructor Destroy; override;
       constructor Create;
       
       function SaveToFile(Fichier: string): integer;
       function LoadFromFile(Fichier: string): integer;

    end;









implementation

uses modTemplateMotor;

procedure mtuTemplateSetCondition(t: TTemplatePage; Droits: TSTunnelUserGameDroit);
var i: TTunnelUserGameDroit;
begin

   for i := tudFlotteEnvoiDePartout to tudAllowRelogin  do begin
      t.ConditionSet(CNT_VAR_ROBOT_USEREDIT_COND_DROITS[i], i in Droits);
   end;

end;




{*******************************************************************************
 ******************************************************************************* 
 **               TCollectionTunnelUserInfos                                     **
 *******************************************************************************
 *******************************************************************************}


function TCollectionTunnelUserInfos.LoadFromFile(Fichier: string): integer;
var Element: TTunnelUserInfos;
    F: TFileStream;
    NbElement: integer;
    i: integer;
begin


    if Fichier = '' then Fichier := FFIchier;
    
    // ATTENTION: Les éléments sont effacés avant le chargement, à modifier en fonction de ce que l'on veut
    Clear;
    
    Result  := 0;
    Fichier := sfcUnixPathToDosPath(Fichier);
    FFichier := Fichier;
    if FileExists(Fichier) = false then exit;
    

    try
      F := TFileStream.Create(Fichier, fmOpenRead);
    except
      F := nil;
    end;


    if F = nil then begin
       Result := -1;
       exit;
    end;

    if F.Size < SizeOf(TTunnelUserInfos) then begin
       // fichier trop petit
       Result := 0;
       F.Free;
       exit;
    end;

    F.Read(NbElement, SizeOf(NbElement));
    
    for i := 1 to NbElement do begin


           if F.Read(Element, SizeOf(TTunnelUserInfos)) < SizeOf(TTunnelUserInfos) then begin
              // echec de lecture
              break;
           end;

           Add(Element);

    end;
    
    // Fermeture du fichier
    F.Free;
    
end;


function TCollectionTunnelUserInfos.SaveToFile(Fichier: string): integer;
var i: integer;
    F: TFileStream;
    pElement: PTunnelUserInfos;
begin

    Result := -2;

    if Fichier = '' then Fichier := FFichier;

    try
       F := TFileStream.Create(Fichier, fmCreate);
    except
       F := nil;
    end;

    if F = nil then begin
       Result := -1;
       exit;
    end;

    i := Count;
    F.Write(i, SizeOf(i));

    for i := 0 to Count - 1 do begin
        pElement := Items[i];
        
        //
        // Ecriture ici
        //
        F.Write(pElement^, SizeOf(TTunnelUserInfos));
    end;

    // Résultat
    Result := Count;
    
    // Ferme le fichier
    F.Free;
    
end;

constructor TCollectionTunnelUserInfos.Create;
begin
    
    // Héritage
    InHerited Create;
    
    
    
    // Code pour l'initialisation ici
    
    
end;

destructor TCollectionTunnelUserInfos.Destroy;
begin
    // Implémenter le code avant l'héritage de la méthode
    // C'est à dire ici
    
   
    // On appelle NOTRE clear qui lui-même appelle NOTRE Delete qui libère l'espace mémoire
    // avant d'enlever le pointeur de la TList
    // L'héritage de Destroy appelle Clear, mais es-ce le notre ou celui de la classe de base ?
    Clear;
    
    
    // Héritage
    InHerited Destroy;
end;


procedure TCollectionTunnelUserInfos.Clear;
var i: integer;
begin

    if Count > 0 then begin
        For i := Count -1 downto 0 do
            Delete(i);
    end;
    
    inherited Clear;
end;


function TCollectionTunnelUserInfos.Get_Pointeur(const Element: string): PTunnelUserInfos;
var i: integer;
begin

   Result := nil;
   
   i := Get_Index(Element);
   if i < 0 then exit;
   Result := Items[i];

end;


function TCollectionTunnelUserInfos.Get_Index(const Element: string): integer;
var i: integer;
    xEle, xTest: string;
    pElement: PTunnelUserInfos;
begin

   Result := -1;

   if Count <= 0 then exit;
   xEle := lowercase(Element);

   for i := 0 to Count - 1 do begin

      pElement := Items[i];          {### ### ### ### ### ### ### ### ### ### ### ### ### ### }
      xTest := pElement^.Username;        {### Neccessite adpation en fonction du type record  ### }
      xTest := lowercase(xTest);     {### ### ### ### ### ### ### ### ### ### ### ### ### ### }


      if xEle = xTest then begin
         Result := i;
         exit;
      end;
   end;


end;

function TCollectionTunnelUserInfos.Add_Update(Element: TTunnelUserInfos): PTunnelUserInfos;
var i : integer;
begin

     Result := nil;
                                         {### ### ### ### ### ### ### ### ### ### ### ### ### ### }
     i := Get_Index(Element.Username);        {### Neccessite adpation en fonction du type record  ### }
                                         {### ### ### ### ### ### ### ### ### ### ### ### ### ### }
     if i < 0 then begin 
        // L'élément n'existe pas, l'ajoute
        Result  := Add(Element);
     end else begin
        // L'élément existe déjà, le met à jour
        Result  := Items[i];     // Obtient le pointeur
        Result^ := Element;
     end;
     
end;




function TCollectionTunnelUserInfos.Get_Item(Index: integer): TTunnelUserInfos;
var pElement: PTunnelUserInfos;
begin

     if Index < 0 then exit;
     if Index >= Count then exit;

     pElement := Items[Index];     // Obtient le pointeur
     Result := pElement^;

end;

function TCollectionTunnelUserInfos.Delete(Index: integer): boolean;
var pElement: PTunnelUserInfos;
begin

    Result := false;

    if (Index < 0) or (Index >= Count) then
       // Hors limite
       exit;


    // Obtient le pointeur
    pElement := Items[Index];

    if pElement <> nil then
       // Libére la mémoire créée lors de l'ajout
       Dispose(pElement);

    // Supprime le pointeur de la liste
    inherited Delete(Index);

    // Met le resultat à True
    Result := true;

end;

function TCollectionTunnelUserInfos.Delete(Element: string): boolean;
var i : integer;
begin

    Result := false;
    i      := Get_Index(Element);

    if i >= 0 then begin
       // Element trouvé
       // Le supprime
       Delete(i);

       // Même si la suppression Echoue on renvoi True
       // Car l'élément a été trouvé
       Result := true;
    end;
end;


function TCollectionTunnelUserInfos.Add(Element: TTunnelUserInfos): PTunnelUserInfos;
var pElement: PTunnelUserInfos;
begin
    
    Result := nil;
    
    New(pElement);          // Créer l'espace mémoire requis
    pElement^ := Element;   // Recopie les données dans l'emplacement pointé
    
    try
       inherited Add(pElement);  // Ajoute le pointeur à la liste
       Result := pElement;
    except
       Result := nil;
    end;
    
    // Pour libérer la mémoire occupé par l'élément pointer:  Dispose(pElement);

end;

// Simple ajout de pointeur
procedure TCollectionTunnelUserInfos.SimpleAdd(Pointeur: PTunnelUserInfos);
begin
    
    inherited Add(Pointeur);  // Ajoute le pointeur à la liste
    
end;

function TCollectionTunnelUserInfos.GetItemx(Index: integer): TTunnelUserInfos;
var pElement: PTunnelUserInfos;
begin

   if Count < 0 then exit;
   if Index >= Count then exit;

   pElement := Items[Index];
   Result := pElement^;

end;



end.
